﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace AndersLiu.EmailQueue
{
	/// <summary>
	/// 表示Email发送队列。
	/// </summary>
	public class EmailQueue
	{
		public EmailQueue Instance
		{
			get { return _instance; }
		}

		/// <summary>
		/// 将一个邮件消息放入发送队列。
		/// </summary>
		/// <param name="message"></param>
		public void Enque(EmailQueueMessage message)
		{
			using (EmailQueueDataContext db = new EmailQueueDataContext(_connStr))
			{
				db.Messages.InsertOnSubmit(message.CreateMessageEntity());
				db.SubmitChanges();
			}
		}

		/// <summary>
		/// 从发送队列中取出一个消息。
		/// </summary>
		/// <returns></returns>
		public EmailQueueMessage Deque(string applicationName)
		{
			Message msg = null;

			lock (_dequeSyncRoot)
			{
				using (EmailQueueDataContext db = new EmailQueueDataContext(_connStr))
				{
					msg = db.Messages.FirstOrDefault(m => m.ApplicationName == applicationName);
					db.Messages.DeleteOnSubmit(msg);
					db.SubmitChanges();
					return EmailQueueMessage.FromMessageEntity(msg);
				}
			}
		}

		EmailQueue()
		{
			_connStr = EmailQueueConfigSection.GetConfig().ConnectionString.ConnectionString;
		}

		string _connStr;

		static object _dequeSyncRoot = new object();
		static EmailQueue _instance = new EmailQueue();
	}

	/// <summary>
	/// 表示Email发送队列中的一个消息。
	/// </summary>
	public class EmailQueueMessage
	{
		/// <summary>
		/// 应用程序名字。该属性决定了使用哪些Email服务器来发送该消息。
		/// </summary>
		public string ApplicationName { get; set; }

		/// <summary>
		/// 收件人地址。
		/// </summary>
		public string[] ToAddress { get; set; }

		/// <summary>
		/// 邮件的标题。
		/// </summary>
		public string Subject { get; set; }

		/// <summary>
		/// 邮件正文。
		/// </summary>
		public string Body { get; set; }

		/// <summary>
		/// 是否使用HTML格式。
		/// </summary>
		public bool IsHtml { get; set; }

		/// <summary>
		/// 从当前消息对象创建数据库实体。
		/// </summary>
		/// <returns></returns>
		internal Message CreateMessageEntity()
		{
			return new Message
			{
				Id = Guid.NewGuid(),
				AddedTime = DateTime.Now,

				ApplicationName = this.ApplicationName,
				ToAddresses = this.MergeToAddresses(),
				Subject = this.Subject,
				Body = this.Body,
				IsHtml = this.IsHtml,
			};
		}

		/// <summary>
		/// 从数据库实体对象创建消息。
		/// </summary>
		/// <param name="msg"></param>
		/// <returns></returns>
		internal static EmailQueueMessage FromMessageEntity(Message msg)
		{
			return new EmailQueueMessage
			{
				ApplicationName = msg.ApplicationName,
				ToAddress = SplitToAddresses(msg.ToAddresses),
				Subject = msg.Subject,
				Body = msg.Body,
				IsHtml = msg.IsHtml,
			};
		}

		string MergeToAddresses()
		{
			StringBuilder sb = new StringBuilder();
			foreach (var addr in this.ToAddress)
			{
				sb.Append(addr);
				sb.Append(";");
			}

			if (sb.Length > 0)
				sb.Remove(sb.Length - 1, 1);

			return sb.ToString();
		}

		static string[] SplitToAddresses(string addrs)
		{
			var ss = addrs.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
			return ss;
		}
	}
}
